/*******************************************************************************************
Copyright (C) 2013 Mestrelab Research S.L. All rights reserved.

This file is part of the MNova scripting toolkit.

Authorized users of MNova Software may use this file freely, but this file is provided AS IS
with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE.
*******************************************************************************************/

/*globals nmr, serialization, settings, Application, BinaryStream, Dir, File, FileDialog, MnUi, NMRSpectrum, ProgressDialog, Str, TextStream*/
/*jslint plusplus: true, indent: 4*/

function importSiemensRda() {
	"use strict";

	function getSiemensRdaParam(aParamName, aHeader, aExpectedRealNumber) {
		var nlPos, value, periodPos, commaPos,
			parPos = aHeader.indexOf(aParamName);
		if (parPos === -1) {
			return undefined;
		}

		nlPos = aHeader.indexOf("\n", parPos);
		if (nlPos === -1) {
			nlPos = aHeader.length;
		}

		value = aHeader.substring(parPos + aParamName.length + 1, nlPos).replace(/^ */, "");
		if (aExpectedRealNumber !== undefined && aExpectedRealNumber) {
			periodPos = value.indexOf('.');
			commaPos = value.indexOf(',');
			if (periodPos<commaPos) {
				value = value.replace(".", "").replace(",", ".");
			}
		}
		return value;
	}

	var fi, fileName, fin, sin, header, headerEnd, re, im, realValues, imagValues,
		i, spectrum, proc, specSize, frequency, nucleus, fromPPM, endPPM, step, refFreq,
		dirSetKey = "importSiemensRda/Dir", progressBar, auxFileName,
		openDir = settings.value(dirSetKey, Dir.home()),
		fileNames = FileDialog.getOpenFileNames("Siemens Syngo (*.rda)", "", openDir),
		headerRes, headerRE = new RegExp("\\s*>>> End of header <<<\\s+");

	if (!fileNames.length) {
		return;
	}

	//Create a progress bar in order to inform to the user about the state of the import process
	progressBar = new ProgressDialog();
	progressBar.minimum = 0;
	progressBar.maximum = 100;
	progressBar.value = 0;
	progressBar.visible = true;

	serialization.fileHistory = false;
	for (fi = 0; fi < fileNames.length && !progressBar.wasCanceled; fi++) {
		fileName = fileNames[fi];
		fin = new File(fileName);

		//Update progress bar
		auxFileName = fileName.substring(fileName.lastIndexOf("/") + 1, fileName.length);
		progressBar.labelText = "Importing " + auxFileName + " file";
		progressBar.value = (fi / fileNames.length) * 100;
		progressBar.update();

		if (!fi) {
			settings.setValue(dirSetKey, fin.absDirPath);
		}

		fin.open(File.ReadOnly);
		sin = new BinaryStream(fin);
		sin.endianness = BinaryStream.eLittle;
		header = sin.readBytes(fin.size).toString("utf-8");

		headerRes = headerRE.exec(header);
		if (headerRes === null) {
			fin.close();
		} else {
			headerEnd = headerRes.index + headerRes[0].length;
			header = header.substring(0, headerEnd);
			sin.pos = headerEnd;
			//Get needed parameter to create the spectrum. To guess ppm values we use the formula  1 / (dim1_step × synthesizer_frequency)
			specSize = Number(getSiemensRdaParam("VectorSize", header));
			nucleus = getSiemensRdaParam("Nucleus", header);
			frequency = Number(getSiemensRdaParam("MRFrequency", header, true));
			step = Number(Number(getSiemensRdaParam("DwellTime", header, true)) * 1e-6);
			refFreq = frequency - 1e-6 / (2.0 * step);
			fromPPM = 0;
			endPPM = (1 / (step * refFreq));

			//Create the spectrum object
			spectrum = importSiemensRda.createSpectrum(specSize, nucleus, frequency, fromPPM, endPPM, fileName);

			//If the spectrum is fine we fill it with data
			if (spectrum !== undefined) {

				//Get the spectrum data in time domain
				realValues = [];
				imagValues = [];
				for (i = 0; i < specSize && !progressBar.wasCanceled; i++) {
					re = sin.readReal64();
					im = sin.readReal64();
					realValues.push(re);
					imagValues.push(im);
				}

				//Fill spectrum using fid method because we are working in the time domain
				if (realValues.length > 0 && imagValues.length > 0) {
					nmr.beginFidModification(spectrum);
					spectrum.fidSetReal("all", realValues);
					spectrum.fidSetImag("all", imagValues);
					nmr.endFidModification(spectrum);
					Application.mainWindow.activeDocument.update();
					spectrum.update();
				}

				//Apply processing parameters in order to get the Fourier Transform
				//The last processing parameter allows to match the number of points (spectral size)
				if (spectrum.isValid()) {
					proc = spectrum.proc;
					proc.setParameter("FT[1].Invert", true);
					proc.setParameter("FT[1].Quadrature", true);
					proc.setParameter("ZF[1].size", spectrum.fidCount(1) * 2);
					spectrum.fitToHeight();
					spectrum.process(proc);
					spectrum.update();
				}
			}
			fin.close();
		}
	}
	if (Application.mainWindow.activeDocument !== undefined) {
		Application.mainWindow.activeDocument.update();
	}

	//Finalize progressBar and manage the history
	serialization.fileHistory = true;
	progressBar.value = 100;
	progressBar.visible = false;
}

importSiemensRda.createSpectrum = function createSpectrum(aSize, aNuc, aMhz, aPpm1, aPpm2, aFileName) {
	"use strict";

	var spectrum;

	//Create spectrum object
	spectrum = new NMRSpectrum(
		{
			1: { nucleus: aNuc, frequency: aMhz, from_ppm: aPpm1, to_ppm: aPpm2, size: aSize },
			filename: aFileName,
			origin: 'RDA file',
			title: ''
		}
	);

	return spectrum;
};

if (this.MnUi && MnUi.scripts_nmr) {
	MnUi.scripts_nmr.scripts_nmr_ImportSiemensSyngo = importSiemensRda;
}
